package ferp.center.server.backend;

import ferp.center.server.Action;
import ferp.center.server.entity.Range;
import ferp.center.server.entity.Rating;
import ferp.center.server.ranking.Lookup;
import ferp.center.server.task.TaskRangeTreeRemoveLeaf;

import javax.persistence.EntityManager;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;

/**
 * User: olegs
 * Date: 3/6/13 10:43 PM
 */
public class RangeTreeMaintenance extends HttpServlet
{
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    Action.queueTaskForBackend(response, "RT maintenance", "/rt/maintenance");
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
  {
    Action.execute(request, new Action.Task()
    {
      @SuppressWarnings("unchecked")
      public void run(EntityManager em, HttpServletRequest request) throws IOException
      {
        removeEmptyLeaves(em);
      }
    });
  }

  private static final int CHUNK_SIZE = 1000;

  private void removeEmptyLeaves(EntityManager em)
  {
    long empty = 0;

    log("looking for empty RT leaves...");

    try
    {
      int offset = 0;

      for (List<Range> leaves = Range.leaves(em, offset, CHUNK_SIZE); leaves.size() > 0; offset += leaves.size(), leaves = Range.leaves(em, offset, CHUNK_SIZE))
        for (Range leaf : leaves)
        {
          List<Rating> ratings = Lookup.ratings(em, leaf);

          if (ratings.size() == 0)
          {
            ++empty;
            // queue empty leaf for removal
            TaskRangeTreeRemoveLeaf.queue(leaf);
          }
        }
    }
    finally
    {
      log("empty leaves found: " + empty);
    }
  }

  // remove ratings with old configuration string (less than 6 characters long)
  private void removeOldRatings(EntityManager em)
  {
    long processed = 0, detached = 0, old = 0, deleted = 0;

    log("looking for detached or old config code ratings...");

    try
    {
      int offset = 0;

      for (List<Rating> ratings = Rating.all(em, offset, CHUNK_SIZE); ratings.size() > 0; offset += ratings.size(), ratings = Rating.all(em, offset, CHUNK_SIZE))
        for (Rating r : ratings)
        {
          boolean flag = false;

          if (r.getConfiguration().length() < 6)
          {
            ++old;

            flag = true;
          }

          if (r.getRange() == null)
          {
            ++detached;

            flag = true;
          }

          if (flag)
          {
            em.remove(r);

            ++deleted;
          }

          ++processed;
        }
    }
    finally
    {
      log("total ratings processed: " + processed);
      log("detached: " + detached + ", old: " + old + ", deleted: " + deleted);
    }
  }
}
